import org.springframework.web.servlet.support.RequestContextUtils as RCU;
import com.fiehn.context.AppContext;

/**
 * tag lib for pagination
 */
class PaginateTagLib implements com.opensymphony.module.sitemesh.RequestConstants {
  def out // to facilitate testing

  protected getPage() {
    return request[PAGE]
  }

/**
 * Creates next/previous links to support pagination for the current controller
 *
 * <g:customPaginate total="${Account.count()}" />
 */
  def customPaginate = { attrs ->
    if (attrs.total == null)
      throwTagError("Tag [paginate] is missing required attribute [total]")

    def messageSource = AppContext.getApplicationContext().getBean("messageSource")
    def locale = RCU.getLocale(request)

    def total = attrs.total.toInteger()
    def action = (attrs.action ? attrs.action : 'list')
    def offset = params.offset?.toInteger()
    def max = params.max?.toInteger()
    def maxsteps = (attrs.maxsteps ? attrs.maxsteps.toInteger() : 10)

    if (!offset) offset = (attrs.offset ? attrs.offset.toInteger() : 0)
    if (!max) max = (attrs.max ? attrs.max.toInteger() : 10)

    def linkParams = [offset: offset - max, max: max]
    if (params.sort) linkParams.sort = params.sort
    if (params.order) linkParams.order = params.order
    if (attrs.params) linkParams.putAll(attrs.params)

    def linkTagAttrs = [action: action]
    if (attrs.controller) {
      linkTagAttrs.controller = attrs.controller
    }
    if (attrs.id) {
      linkTagAttrs.id = attrs.id
    }
    linkTagAttrs.params = linkParams

    // determine paging variables
    def steps = maxsteps > 0
    int currentstep = (offset / max) + 1
    int firststep = 1
    int laststep = Math.round(Math.ceil(total / max))

    //include the css file
    out << "<style type=\"text/css\">@import url(\"${createLinkTo(dir: 'css', file: 'pagination.css')}\");</style>"

    out << "<table border=0 align='left' valign='middle'><tr>"
    out << "<td class='paginationlabel' align='left'> Total Records : ${total} &nbsp;</td>"

    // display previous link when not on firststep
    if (currentstep > firststep) {
      //linkTagAttrs.class = 'prevLink'

      out << "<td class=\"prevLink\" title='Click to get previous page'>"
      out << link(linkTagAttrs.clone()) {
        (attrs.prev ? attrs.prev : messageSource.getMessage('default.paginate.prev', null, 'Previous', locale))
      }
      out << "</td>"
    } else {
      out << "<td class=\"prevLink-off\">"
      out << (attrs.prev ? attrs.prev : messageSource.getMessage('default.paginate.prev', null, 'Previous', locale))
      out << "</td>"
    }

    // display steps when steps are enabled and laststep is not firststep
    if (steps && laststep > firststep) {
      //linkTagAttrs.class = 'step'

      // determine begin and endstep paging variables
      int beginstep = currentstep - Math.round(maxsteps / 2) + (maxsteps % 2)
      int endstep = currentstep + Math.round(maxsteps / 2) - 1

      if (beginstep < firststep) {
        beginstep = firststep
        endstep = maxsteps
      }
      if (endstep > laststep) {
        beginstep = laststep - maxsteps + 1
        if (beginstep < firststep) {
          beginstep = firststep
        }
        endstep = laststep
      }

      // display firststep link when beginstep is not firststep
      if (beginstep > firststep) {
        linkParams.offset = 0

        out << "<td class=\"step\" title='Click to get page-1'>"
        out << link(linkTagAttrs.clone()) {firststep.toString()}
        out << "</td>"
        out << '<td>..</td>'
      }

      // display paginate steps
      (beginstep..endstep).each { i ->
        if (currentstep == i) {
          out << "<td class=\"currentStep\">${i}</td>"
        }
        else {
          linkParams.offset = (i - 1) * max
          out << "<td class=\"step\" title='Click to get page-${i}'>"
          out << link(linkTagAttrs.clone()) {i.toString()}
          out << "</td>"
        }
      }

      // display laststep link when endstep is not laststep
      if (endstep < laststep) {
        out << '<td>..</td>'
        linkParams.offset = (laststep - 1) * max
        out << "<td class=\"step\" title='Click to get page-${laststep}'>"
        out << link(linkTagAttrs.clone()) { laststep.toString() }
        out << "</td >"
      }
    } else {
      out << "<td class=\"currentStep\">1</td>"                   
    }

    // display next link when not on laststep
    if (currentstep < laststep) {
      //linkTagAttrs.class = 'nextLink'
      linkParams.offset = offset + max
      out << "<td class=\"nextLink\" title='Click to get next page'>"
      out << link(linkTagAttrs.clone()) {
        (attrs.next ? attrs.next : messageSource.getMessage('default.paginate.next', null, 'Next', locale))
      }
      out << "</td >"
    } else {
      out << "<td class=\"nextLink-off\">"
      out << (attrs.next ? attrs.next : messageSource.getMessage('default.paginate.next', null, 'Next', locale))
      out << "</td >"
    }
    out << "</tr></table>"
  }

}
